package main

import (
	"errors"
	"fmt"
	"go-tcp-server/frame"
	"go-tcp-server/metrics"
	"go-tcp-server/packet"
	"net"
	"net/http"
	_ "net/http/pprof"
)

func main() {

	go func() {
		http.ListenAndServe(":6060", nil)
	}()

	// 服务端程序监听 9999 端口
	listen, err := net.Listen("tcp", ":9998")
	if err != nil {
		fmt.Println("listen error:", err)
		return
	}

	fmt.Println("server start ok(on *.9998)")

	for {
		// 调用 Accept 方法后得到一个新连接
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("accept error:", err)
			break
		}
		// 创建 goroutine 处理连接请求
		go handleConnection(conn)
	}

}

// 处理连接
func handleConnection(conn net.Conn) {
	// 连接建立，ClientConnected加1
	metrics.ClientConnected.Inc()
	defer func() {
		// 连接断开，ClientConnected减1
		metrics.ClientConnected.Dec()
		conn.Close()
	}()
	frameCodec := frame.NewFrameCodec()
	for {
		// 解码
		framePayload, err := frameCodec.Decode(conn)
		if err != nil {
			fmt.Printf("handleConnection: frameCodec.Decode error \n", err)
			return
		}
		// 收到并解码一个消息请求，ReqReceivedTotal消息计数器加1
		metrics.ReqReceivedTotal.Add(1)
		// 简单处理一下 packet
		ackFramePayload, err := handlePacket(framePayload)
		if err != nil {
			fmt.Println("handleConn: handle packet error:", err)
			return
		}

		// 将处理完的 ackFramePayload 写回 conn
		err = frameCodec.Encode(conn, ackFramePayload)
		if err != nil {
			fmt.Println("handleConn: frameCodec.Encode error:", err)
			return
		}
		// 返回响应后，RspSendTotal消息计数器加1
		metrics.RspSendTotal.Add(1)
	}
}

// 模拟处理数据包
func handlePacket(framePayload []byte) (ackFramePayload []byte, err error) {
	var p packet.Packet
	if p, err = packet.Decode(framePayload); err != nil {
		fmt.Println("handlePacket: packet.Decode error ", err)
		return
	}

	switch p.(type) {
	case *packet.SubmitRequest:
		submitRequest := p.(*packet.SubmitRequest)
		fmt.Printf("recevied submit: id = %s, payload=%s\n", submitRequest.ID, string(submitRequest.Payload))

		submitRequestAck := &packet.SubmitRequestAck{
			ID:     submitRequest.ID,
			Result: 0,
		}
		// // 将submitRequest对象归还给Pool池
		packet.SubmitPool.Put(submitRequest)
		ackFramePayload, err := packet.Encode(submitRequestAck)
		if err != nil {
			return nil, err
		}
		return ackFramePayload, nil
	default:
		return nil, errors.New("unknown packet type")
	}
}
